// Copyright 2004-present Facebook. All Rights Reserved.

#pragma once
#include <fboss/lib/phy/gen-cpp2/phy_types.h>
#include <folly/MacAddress.h>
#include "fboss/agent/gen-cpp2/switch_config_types.h"
#include "fboss/agent/types.h"

namespace facebook::fboss {

class HwAsic {
 public:
  HwAsic(
      std::optional<int64_t> switchId,
      const cfg::SwitchInfo& switchInfo,
      std::optional<cfg::SdkVersion> sdkVersion = std::nullopt,
      std::unordered_set<cfg::SwitchType> supportedModes = {
          cfg::SwitchType::NPU});
  enum class Feature {
    // ACL Features::
    //
    // ACL Entry:
    //   - Consists of Matcher and Action
    //   - Matcher: check if patcket matches criteria e.g. specific source IP.
    //   - Action: perform action on match e.g. drop packet
    //
    // ACL Counter:
    //   - Can be optionally attached to an ACL entry.
    //   - Can be configured to count the number of bytes and/or packets that
    //     matched that ACL entry.
    //
    // ACL Table:
    //  - Ordered list of ACL entries
    //  - Only the first matching ACL entry and its Action take effect.
    //
    // ACL Table Group:
    //  - Group of ACL Tables
    //  - First matching ACL entry in each table and its Action takes effect.
    //
    // Bind point:
    //  - Where to attach the ACL e.g. switch (global), per port etc.
    //  - FBOSS supports only switch level ACLs i.e. ACL will be checked for
    //    very packet in the switch.
    //
    // Stage:
    //  - Stage in the pipeline the ACL will be checked.
    //  - For example: ingress, egress etc.
    //

    // Set to true if Multiple ACL Tables are supported
    // TODO:
    //  - Candidate for removal: YES, ACL_TABLE_GROUP is enabled everywhere.
    //  - Consolidate to a single feature prefixed with ACL_
    MULTIPLE_ACL_TABLES,
    ACL_TABLE_GROUP,

    // Set to true if SAI implementations allow individually enabling Packet
    // counter and byte counter.
    // On some SAI implementations, supporting this is non-trivial. Those SAI
    // implementations enable bytes as well as packet counters even if only one
    // of the two is enabled.
    // TODO:
    //   - Candidate for removal: YES. FBOSS use case does not require enabling
    //     only one. Enforce that either both are enabled or neither is enabled
    //     on every platform, and then remove this feature.
    //   - If we decide to keep the feature, rename to carry ACL_ prefix.
    SEPARATE_BYTE_AND_PACKET_ACL_COUNTER,

    // Set to true if Ingress ACLs are supported.
    // Used to bind an ACL Table or ACL Table Group to a switch using
    // SAI_SWITCH_ATTR_INGRESS_ACL
    // TODO:
    //  - Candidate for removal: YES. All ASICs/SDKs already support this.
    SWITCH_ATTR_INGRESS_ACL,

    // Set to true if Egress ACL Table is supported.
    // However, this Table sits post lookup but before buffering.
    // Thus, named as INGRESS_POST_LOOKUP_ACL_TABLE.
    // For SAI, this maps to SAI_ACL_STAGE_EGRESS.
    // TODO:
    //  - Rename to carry ACL_ prefix.
    INGRESS_POST_LOOKUP_ACL_TABLE,

    // Set to true if Empty Matcher can be used to match all packets.
    // TODO:
    //  - Rename to carry ACL_ prefix.
    EMPTY_ACL_MATCHER,

    // Set to true if Metadata qualifier is supported for ACLs.
    // Metadata is an integer field that can be associated with an L2 entry,
    // Neighbor entry, Route entry etc. When that L2/Neighbor/Route enetry is
    // hit, the corresponding Metadata is  associated with the packet. This
    // packet can match any ACL that carries the same Metadata in the matcher
    // field and corresponding ACL action takes effect.
    ACL_METADATA_QUALIFER,

    // Set to true if the SAI implementation supports setting a
    // label (string identifier) for an ACL counter.
    // This label can be used to uniquely identify ACL counter
    // object during warmboot.  The support was added by SAI community PR 1430,
    // and is part of the SAI spec since v1.10.0.
    ACL_COUNTER_LABEL,

    // Set to true if the SAI implementation supports Ether type as ACL matcher
    // For SAI, this maps to whether SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE can be
    // set during ACL Table creation.
    // TODO:
    //  - Candidate for removal: YES, but non-trivial.
    //  - Extend SAI spec sai_acl_capability_t to return the list of ACL
    //    matchers supported.
    //  - Work with SAI implementations to support this capability.
    //  - Extend FBOSS to query supported matchers for a given stage e.g.
    //    SAI_SWITCH_ATTR_ACL_STAGE_INGRESS
    ACL_ENTRY_ETHER_TYPE,

    // Set to true if the SAI implementation supports ACL Byte counters
    // For SAI, this maps to whether SAI_ACL_COUNTER_ATTR_BYTES can be queried.
    // TODO:
    //  - Candidate for removal: YES, but non-trivial.
    //  - Extend SAI spec sai_acl_capability_t to return whether ACL Byte
    //    counters are supported.
    //  - Work with SAI implementations to support this capability.
    //  - Extend FBOSS to query whether ACL Byte counters are supported.
    ACL_BYTE_COUNTER,

    // Packet is dropped due to configured ACL rules, all stages/bind points
    // For SAI this maps to whether debug counter SAI_IN_DROP_REASON_ACL_ANY
    // can be queried.
    // TODO:
    //  - Candidate for removal: YES, but non-trivial.
    //  - Extend SAI spec to support capability_t for Debug counters.
    //  - Work with SAI implementations to support this capability.
    //  - Extend FBOSS to query.
    //  - Rename to carry ACL_ prefix.
    ANY_ACL_DROP_COUNTER,

    // Set to true if the SAI implementation supports Ether type as ACL matcher
    // For SAI, this maps to whether SAI_ACL_TABLE_ATTR_FIELD_{IN, SRC}_PORT can
    // be set during ACL Table creation.
    // TODO:
    //  - Candidate for removal: YES, but non-trivial.
    //  - Extend SAI spec sai_acl_capability_t to return the list of ACL
    //    matchers supported.
    //  - Work with SAI implementations to support this capability.
    //  - Extend FBOSS to query supported matchers for a given stage e.g.
    //    SAI_SWITCH_ATTR_ACL_STAGE_INGRESS
    //  - Rename to carry ACL_ prefix.
    SAI_ACL_ENTRY_SRC_PORT_QUALIFIER,

    // Set to true if the SAI implementation supports ACL action to set hash
    // algorithm. For SAI, this maps to whether
    // SAI_ACL_ACTION_TYPE_SET_ECMP_HASH_ALGORITHM
    // ACL action is supported.
    // TODO:
    //  - Candidate for removal: YES.
    //  - switch_config.AclTable already carries list of actionTypes.
    //  - Start populating that field in the config.
    //  - Populate SAI_ACL_ACTION_TYPE_SET_ECMP_HASH_ALGORITHM action only for
    //    SAI implementations that support this action.
    ACL_SET_ECMP_HASH_ALGORITHM,

    // Set to true if flex counters are supported by ingress field processor.
    // TODO:
    //  - Candidate for removal: YES.
    //  - Only used by non-SAI. Once we completely migrate to SAI, remove.
    INGRESS_FIELD_PROCESSOR_FLEX_COUNTER,
    SAI_ACL_TABLE_UPDATE,
    // Other features
    SPAN,
    ERSPANv4,
    ERSPANv6,
    SFLOWv4,
    SFLOWv6,
    MPLS,
    MPLS_ECMP,
    SAI_MPLS_QOS,
    HASH_FIELDS_CUSTOMIZATION,
    ECN,
    L3_QOS,
    QOS_MAP_GLOBAL,
    QCM,
    SCHEDULER_PPS,
    SMAC_EQUALS_DMAC_CHECK_ENABLED,
    NEXTHOP_TTL_DECREMENT_DISABLE,
    PORT_TTL_DECREMENT_DISABLE,
    PORT_INTERFACE_TYPE,
    WEIGHTED_NEXTHOPGROUP_MEMBER,
    BLACKHOLE_ROUTE_DROP_COUNTER,
    RESOURCE_USAGE_STATS,
    HSDK,
    OBJECT_KEY_CACHE,
    L3_EGRESS_MODE_AUTO_ENABLED,
    SAI_ECN_WRED,
    PKTIO,
    HOSTTABLE,
    PORT_TX_DISABLE,
    ZERO_SDK_WRITE_WARMBOOT,
    OBM_COUNTERS,
    BUFFER_POOL,
    MIRROR_PACKET_TRUNCATION,
    SFLOW_SAMPLING,
    PTP_TC,
    PTP_TC_PCS,
    PENDING_L2_ENTRY,
    EGRESS_QUEUE_FLEX_COUNTER,
    PFC,
    PFC_XON_TO_XOFF_COUNTER, // not supported on MORGAN800CC/KODIAK3
    INGRESS_L3_INTERFACE,
    NON_UNICAST_HASH,
    DETAILED_L2_UPDATE,
    COUNTER_REFRESH_INTERVAL,
    TELEMETRY_AND_MONITORING,
    WIDE_ECMP,
    ALPM_ROUTE_PROJECTION,
    MAC_AGING,
    SAI_PORT_SPEED_CHANGE,
    SFLOW_SHIM_VERSION_FIELD,
    REMOVE_PORTS_FOR_COLDBOOT,
    EGRESS_MIRRORING,
    EGRESS_SFLOW,
    DEFAULT_VLAN,
    SAI_LAG_HASH,
    TRAFFIC_HASHING,
    MACSEC,
    CPU_PORT,
    VRF,
    SAI_HASH_FIELDS_CLEAR_BEFORE_SET,
    SAI_PORT_SERDES_FIELDS_RESET,
    ROUTE_COUNTERS,
    ROUTE_FLEX_COUNTERS,
    BRIDGE_PORT_8021Q,
    FEC_DIAG_COUNTERS,
    SAI_WEIGHTED_NEXTHOPGROUP_MEMBER,
    PORT_EYE_VALUES,
    SAI_MPLS_TTL_1_TRAP,
    SAI_MPLS_LABEL_LOOKUP_FAIL_COUNTER,
    PMD_RX_LOCK_STATUS,
    PMD_RX_SIGNAL_DETECT,
    SAI_FEC_COUNTERS,
    SAI_PORT_ERR_STATUS,
    EXACT_MATCH,
    ROUTE_PROGRAMMING,
    ECMP_HASH_V4,
    ECMP_HASH_V6,
    FEC_CORRECTED_BITS,
    MEDIA_TYPE,
    FEC,
    RX_FREQUENCY_PPM,
    RX_SERDES_PARAMETERS,
    FABRIC_PORTS,
    ECMP_MEMBER_WIDTH_INTROSPECTION,
    SAI_FIRMWARE_PATH,
    EXTENDED_FEC,
    LINK_TRAINING,
    SAI_RX_REASON_COUNTER,
    SAI_MPLS_INSEGMENT,
    RESERVED_ENCAP_INDEX_RANGE,
    VOQ,
    XPHY_PORT_STATE_TOGGLE,
    SAI_PORT_GET_PMD_LANES,
    FABRIC_TX_QUEUES,
    SAI_PORT_VCO_CHANGE,
    SAI_TTL0_PACKET_FORWARD_ENABLE,
    WARMBOOT,
    SHARED_INGRESS_EGRESS_BUFFER_POOL,
    ROUTE_METADATA,
    ARS,
    P4_WARMBOOT,
    IN_PAUSE_INCREMENTS_DISCARDS,
    IN_DISCARDS_EXCLUDES_PFC,
    FEC_AM_LOCK_STATUS,
    PCS_RX_LINK_STATUS,
    TC_TO_QUEUE_QOS_MAP_ON_SYSTEM_PORT,
    SAI_CONFIGURE_SIX_TAP,
    UDF_HASH_FIELD_QUERY,
    SAI_SAMPLEPACKET_TRAP,
    PORT_FABRIC_ISOLATE,
    QUEUE_ECN_COUNTER,
    CPU_TX_VIA_RECYCLE_PORT,
    SAI_CONFIGURE_SEVEN_TAP,
    SWITCH_DROP_STATS,
    PACKET_INTEGRITY_DROP_STATS,
    SAI_UDF_HASH,
    INGRESS_PRIORITY_GROUP_HEADROOM_WATERMARK,
    RX_LANE_SQUELCH_ENABLE,
    SAI_PORT_ETHER_STATS,
    SLOW_STAT_UPDATE, // pending CS00012299308
    VOQ_DELETE_COUNTER,
    DRAM_ENQUEUE_DEQUEUE_STATS,
    ARS_PORT_ATTRIBUTES,
    SAI_EAPOL_TRAP,
    // pending CS00012311423
    L3_MTU_ERROR_TRAP,
    SAI_USER_DEFINED_TRAP,
    CREDIT_WATCHDOG,
    ECMP_DLB_OFFSET,
    SAI_FEC_CORRECTED_BITS,
    SAI_FEC_CODEWORDS_STATS,
    LINK_INACTIVE_BASED_ISOLATE,
    SAI_PORT_SERDES_PROGRAMMING,
    RX_SNR,
    MANAGEMENT_PORT,
    ANY_TRAP_DROP_COUNTER,
    PORT_WRED_COUNTER,
    PORT_SERDES_ZERO_PREEMPHASIS,
    EGRESS_FORWARDING_DROP_COUNTER,
    SAI_PRBS,
    RCI_WATERMARK_COUNTER,
    DTL_WATERMARK_COUNTER,
    LINK_ACTIVE_INACTIVE_NOTIFY,
    PQP_ERROR_EGRESS_DROP_COUNTER,
    FABRIC_LINK_DOWN_CELL_DROP_COUNTER,
    CRC_ERROR_DETECT,
    EVENTOR_PORT_FOR_SFLOW,
    SAI_ECMP_HASH_ALGORITHM,
    SWITCH_REACHABILITY_CHANGE_NOTIFY,
    CABLE_PROPOGATION_DELAY,
    DRAM_BLOCK_TIME,
    VOQ_LATENCY_WATERMARK_BIN,
    DATA_CELL_FILTER,
    EGRESS_CORE_BUFFER_WATERMARK,
    DELETED_CREDITS_STAT,
    INGRESS_PRIORITY_GROUP_DROPPED_PACKETS,
    // replace all ACL based trap reasons by
    // explicty ACL config programmed by FBOSS
    NO_RX_REASON_TRAP,
    EGRESS_GVOQ_WATERMARK_BYTES,
    INGRESS_PRIORITY_GROUP_SHARED_WATERMARK,
    MULTIPLE_EGRESS_BUFFER_POOL,
    ENABLE_DELAY_DROP_CONGESTION_THRESHOLD,
    PORT_MTU_ERROR_TRAP,
    L3_INTF_MTU,
    DEDICATED_CPU_BUFFER_POOL,
    FAST_LLFC_COUNTER,
    INGRESS_SRAM_MIN_BUFFER_WATERMARK,
    FDR_FIFO_WATERMARK,
    EGRESS_CELL_ERROR_STATS,
    CPU_QUEUE_WATERMARK_STATS,
    SAMPLE_RATE_CONFIG_PER_MIRROR,
    SFLOW_SAMPLES_PACKING,
    VENDOR_SWITCH_NOTIFICATION,
    SDK_REGISTER_DUMP,
    FEC_ERROR_DETECT_ENABLE,
    BUFFER_POOL_HEADROOM_WATERMARK,
    SAI_SET_TC_WITH_USER_DEFINED_TRAP_CPU_ACTION,
    SAI_HOST_MISS_TRAP,
    CPU_TX_PACKET_REQUIRES_VLAN_TAG,
    DRAM_DATAPATH_PACKET_ERROR_STATS,
    EGRESS_POOL_AVAILABLE_SIZE_ATTRIBUTE_SUPPORTED,
    SWITCH_ASIC_SDK_HEALTH_NOTIFY,
    VENDOR_SWITCH_CONGESTION_MANAGEMENT_ERRORS,
    PFC_WATCHDOG_TIMER_GRANULARITY,
    ASIC_RESET_NOTIFICATIONS,
    SAI_PORT_IN_CONGESTION_DISCARDS,
    TEMPERATURE_MONITORING,
    ROUTER_INTERFACE_STATISTICS,
    CPU_PORT_EGRESS_BUFFER_POOL,
    SET_NEXT_HOP_GROUP_HASH_ALGORITHM,
    BULK_CREATE_ECMP_MEMBER,
    TECH_SUPPORT,
    DRAM_QUARANTINED_BUFFER_STATS,
    MANAGEMENT_PORT_MULTICAST_QUEUE_ALPHA,
    SAI_PORT_PG_DROP_STATUS,
    FABRIC_INTER_CELL_JITTER_WATERMARK,
    MAC_TRANSMIT_DATA_QUEUE_WATERMARK,
    FABRIC_LINK_MONITORING,
    ARS_ALTERNATE_MEMBERS,
    RESERVED_BYTES_FOR_BUFFER_POOL,
    // Indicates the buffer pool size excludes the headroom
    // pool size given the buffer pool size determination is
    // left to vendor SAI implementation.
    INGRESS_BUFFER_POOL_SIZE_EXCLUDES_HEADROOM,
  };

  enum class AsicMode {
    ASIC_MODE_SIM,
    ASIC_MODE_HW,
  };

  enum class AsicVendor {
    ASIC_VENDOR_BCM,
    ASIC_VENDOR_TAJO,
    ASIC_VENDOR_CREDO,
    ASIC_VENDOR_MARVELL,
    ASIC_VENDOR_CHENAB,
    ASIC_VENDOR_MOCK,
    ASIC_VENDOR_FAKE,
  };
  enum FabricNodeRole {
    SINGLE_STAGE_L1,
    DUAL_STAGE_L1,
    DUAL_STAGE_L2,
  };
  enum InterfaceNodeRole {
    IN_CLUSTER_NODE,
    DUAL_STAGE_EDGE_NODE,
  };
  virtual ~HwAsic() {}
  static std::unique_ptr<HwAsic> makeAsic(
      int64_t switchID,
      const cfg::SwitchInfo& switchInfo,
      std::optional<cfg::SdkVersion> sdkVersion,
      std::optional<HwAsic::FabricNodeRole> fabricNodeRole);

  virtual bool isSupported(Feature) const = 0;
  virtual cfg::AsicType getAsicType() const = 0;
  std::string getAsicTypeStr() const;
  virtual AsicVendor getAsicVendor() const = 0;
  virtual AsicMode getAsicMode() const {
    return AsicMode::ASIC_MODE_HW;
  }
  virtual phy::DataPlanePhyChipType getDataPlanePhyChipType() const = 0;
  virtual std::string getVendor() const = 0;
  virtual cfg::PortSpeed getMaxPortSpeed() const = 0;
  virtual std::set<cfg::StreamType> getQueueStreamTypes(
      cfg::PortType portType) const = 0;
  virtual int getDefaultNumPortQueues(
      cfg::StreamType streamType,
      cfg::PortType portType) const = 0;
  virtual int getBasePortQueueId(
      cfg::StreamType /* streamType */,
      cfg::PortType /* portType */) const {
    return 0;
  }
  virtual uint32_t getMaxLabelStackDepth() const = 0;
  virtual uint64_t getMMUSizeBytes() const = 0;
  virtual uint32_t getMaxMirrors() const = 0;
  virtual uint16_t getMirrorTruncateSize() const = 0;
  virtual std::optional<uint64_t> getDefaultReservedBytes(
      cfg::StreamType streamType,
      cfg::PortType portType) const = 0;
  virtual std::optional<cfg::MMUScalingFactor> getDefaultScalingFactor(
      cfg::StreamType streamType,
      bool cpu) const = 0;
  virtual const std::map<cfg::PortType, cfg::PortLoopbackMode>&
  desiredLoopbackModes() const;
  virtual bool mmuQgroupsEnabled() const {
    return false;
  }
  virtual FabricNodeRole getFabricNodeRole() const;
  virtual const std::set<uint16_t>& getL1FabricPortsToConnectToL2() const;

  // Get the smallest packet buffer unit for ASIC, cell size for BCM
  virtual uint32_t getPacketBufferUnitSize() const = 0;

  // Get the size of the buffer descriptor associated with each packet
  virtual uint32_t getPacketBufferDescriptorSize() const = 0;

  /*
    This function will be used in calculating lane assignment, physical port
    assignment when adjusting ports in a port group. Most platforms have
    physical lanes : physical port = 1:1, but due to limited port id, some
    platforms will have different mappings. Note phyiscal port here is referring
    to the chip's physical ports and not our front panel ports
  */
  virtual int getNumLanesPerPhysicalPort() const {
    return 1;
  }

  /*
   * Default Content Aware Processor group ID for ACLs
   */
  virtual int getDefaultACLGroupID() const;

  /*
   * Default Content Aware Processor group ID for TeFlows
   */
  virtual int getDefaultTeFlowGroupID() const;

  /*
   * station entry id for vlan interface
   */
  virtual int getStationID(int intfID) const;
  virtual int getDefaultDropEgressID() const;

  /*
   * The maximum number of logical ports
   */
  virtual int getMaxNumLogicalPorts() const = 0;
  virtual uint32_t getMaxWideEcmpSize() const = 0;

  /*
   * The maximum number of lag member
   */
  virtual uint32_t getMaxLagMemberSize() const = 0;

  /*
   * Port ID offset for system port. Default is 0.
   * This will be added to PortID and will be carried in the
   * sflow shim header
   */
  virtual int getSflowPortIDOffset() const {
    return 0;
  }

  /**
   * Number of forwarding engines / units with its own buffer pool.
   */
  virtual uint32_t getNumCores() const = 0;

  virtual uint32_t getSflowShimHeaderSize() const = 0;

  virtual std::optional<uint32_t> getPortSerdesPreemphasis() const = 0;

  static std::vector<cfg::AsicType> getAllHwAsicList();

  virtual uint32_t getMaxVariableWidthEcmpSize() const = 0;

  virtual uint32_t getMaxEcmpSize() const = 0;

  virtual std::optional<uint32_t> getMaxEcmpGroups() const {
    return std::nullopt;
  }

  virtual std::optional<uint32_t> getMaxEcmpMembers() const {
    return std::nullopt;
  }

  virtual std::optional<uint32_t> getMaxArsGroups() const = 0;
  virtual std::optional<uint32_t> getArsBaseIndex() const = 0;
  // TODO(zecheng): Define more specific limits for v4/v6 routes with different
  // mask lengths
  virtual std::optional<uint32_t> getMaxRoutes() const {
    return 75000;
  }

  //  SAI implementaion doen not support attribute
  //  SAI_SWITCH_ATTR_L3_NEIGHBOR_TABLE_SIZE yet, so decided to add these
  //  functions to return max neighbot table size
  virtual std::optional<uint32_t> getMaxNdpTableSize() const {
    return std::nullopt;
  }

  virtual std::optional<uint32_t> getMaxArpTableSize() const {
    return std::nullopt;
  }

  // Set this if NDP/ARP uses a single unified neighbor table
  virtual std::optional<uint32_t> getMaxUnifiedNeighborTableSize() const {
    return std::nullopt;
  }

  virtual bool scalingFactorBasedDynamicThresholdSupported() const = 0;

  virtual int getBufferDynThreshFromScalingFactor(
      cfg::MMUScalingFactor scalingFactor) const = 0;

  virtual uint32_t getStaticQueueLimitBytes() const = 0;

  virtual cfg::Range64 getReservedEncapIndexRange() const;

  virtual uint32_t getNumMemoryBuffers() const = 0;

  cfg::SwitchType getSwitchType() const {
    return switchType_;
  }
  std::optional<uint64_t> getSwitchId() const {
    return switchId_;
  }
  int16_t getSwitchIndex() const {
    return switchIndex_;
  }
  const cfg::SystemPortRanges& getSystemPortRanges() const {
    return systemPortRanges_;
  }

  virtual cfg::StreamType getDefaultStreamType() const {
    return defaultStreamType_;
  }

  void setDefaultStreamType(cfg::StreamType streamType) {
    defaultStreamType_ = streamType;
  }

  const folly::MacAddress& getAsicMac() const {
    return asicMac_;
  }
  virtual std::optional<uint32_t> computePortGroupSkew(
      const std::map<PortID, uint32_t>& portId2cableLen) const;

  struct RecyclePortInfo {
    uint32_t coreId;
    uint32_t corePortIndex;
    uint32_t speedMbps;
    uint32_t inbandPortId;
  };

  std::optional<cfg::SdkVersion> getSdkVersion() const {
    return sdkVersion_;
  }

  virtual RecyclePortInfo getRecyclePortInfo(
      InterfaceNodeRole /* intfRole */) const;
  cfg::PortLoopbackMode getDesiredLoopbackMode(
      cfg::PortType portType = cfg::PortType::INTERFACE_PORT) const;

  virtual uint32_t getMaxPorts() const;
  virtual uint32_t getVirtualDevices() const;
  virtual std::vector<prbs::PrbsPolynomial> getSupportedPrbsPolynomials()
      const {
    return {};
  }

  virtual std::optional<uint32_t> getMaxAclTables() const {
    return std::nullopt;
  }
  virtual std::optional<uint32_t> getMaxAclEntries() const {
    return std::nullopt;
  }

  virtual uint32_t getThresholdGranularity() const {
    return 1;
  }

  virtual uint32_t getMaxHashSeedLength() const {
    return 32;
  }

  virtual int getMidPriCpuQueueId() const = 0;
  virtual int getHiPriCpuQueueId() const = 0;

  virtual uint64_t getSramSizeBytes() const = 0;
  std::optional<int32_t> getGlobalSystemPortOffset() const {
    return globalSystemPortOffset_;
  }
  std::optional<int32_t> getLocalSystemPortOffset() const {
    return localSystemPortOffset_;
  }
  std::optional<int32_t> getInbandPortId() const {
    return inbandPortId_;
  }
  virtual uint32_t getMaxSwitchId() const;

  virtual uint16_t getGreProtocol() const {
    return 0x88be;
  }

  // Applicable only when IP_IN_IP_DECAP feature is enabled.
  virtual cfg::IpTunnelMode getTunnelDscpMode() const {
    return cfg::IpTunnelMode::PIPE;
  }

  virtual uint64_t getCpuPortEgressPoolSize() const;

  virtual bool portMtuSupported(cfg::PortType portType) const;

 protected:
  static cfg::Range64 makeRange(int64_t min, int64_t max);

 private:
  cfg::SwitchType switchType_;
  std::optional<int64_t> switchId_;
  int16_t switchIndex_;
  cfg::SystemPortRanges systemPortRanges_;
  cfg::StreamType defaultStreamType_{cfg::StreamType::ALL};
  folly::MacAddress asicMac_;
  std::optional<cfg::SdkVersion> sdkVersion_;
  std::optional<int32_t> localSystemPortOffset_, globalSystemPortOffset_,
      inbandPortId_;
};

} // namespace facebook::fboss
